<template>
  <div class="Box">
    <normalBox>
      <!-- <template #title>ref和reactive,使用toRefs进行解构出来的属性具备响应式</template> -->
      <div>
        {{ content }}
        {{ num }}
        <button @click="changeContent">++</button>
        <button @click="changeNum">--</button>
      </div>
    </normalBox>
    <normalBox>
      <div>
        <div>{{ localJson }}</div>
        <button @click="getTestData">获取本地JSON数据的axios封装</button>
      </div>
    </normalBox>
    <normalBox>
      <div>
        <testBox>
          <!-- 从从Vue.js 2.6.0版本开始，slot-scope属性已被弃用，并推荐使用新的v-slot语法。
        v-slot需要配合template使用 -->
          <!-- <div slot-scope="{ sonData }"> -->
          <template v-slot="{ sonData }">
            <div>
              插槽的使用
              <div>{{ sonData }}</div>
            </div>
          </template>
        </testBox>
      </div>
    </normalBox>
    <normalBox>
      <div class="testPop">
        <div v-for="item in foods" :key="item.id + item.name" class="content-box">
          <div class="item">{{ item.name }}</div>
          <div class="pop-box">
            <div class="pop-item" v-for="el in item.content" :key="el.name">
              <div class="child">{{ el.name }}</div>
            </div>
          </div>
        </div>
      </div>
    </normalBox>
    <normalBox>
      <div class="testFlex">
        <div class="bottom" @click="changeShow">点击</div>
        <div class="leftBox"></div>
        <div class="midBox"></div>
        <div class="rightBox" v-show="show"></div>
      </div>
    </normalBox>
    <normalBox>
      <div class="scroll-box">
        <div class="title">滚动监听触发接口事件</div>
        <div class="content" ref="scroll_content_1">
          <div class="item" v-for="(item, index) in scrollData_1" :key="item + index">
            {{ item.context }}
          </div>
        </div>
      </div>
      <div class="scroll-box">
        <div class="title">自动滚动</div>
        <div class="content" ref="scroll_content_2">
          <div class="item" v-for="(item, index) in scrollData_2" :key="item + index">
            {{ item.context }}
          </div>
        </div>
      </div>
      <div class="scroll-box">
        <div class="title">滚动监听触发接口事件-vue命令行封装使用</div>
        <div class="content" v-loadmore="scrollBinding">
          <div class="item" v-for="(item, index) in scrollData_1" :key="item + index">
            {{ item.context }}
          </div>
        </div>
      </div>
      <div class="scroll-box">
        <div class="title">自动滚动-vue命令行封装使用</div>
        <div class="content" v-scroll.mouse="0.5">
          <div class="item" v-for="(item, index) in scrollData_2" :key="item + index">
            {{ item.context }}
          </div>
        </div>
      </div>
    </normalBox>
    <normalBox> </normalBox>
  </div>
</template>
<script setup>
import { ref, reactive, toRefs, onMounted, nextTick, onUnmounted, onBeforeUnmount } from 'vue'
import { debounce, getObjType, deepClone, throttle } from '@/utils/utils'
import Axios from '@/utils/axios'
import state from './data.js'
import normalBox from '@/components/base/normalBox.vue'
/**
 * @description 测试ref和reactive,使用toRefs进行解构出来的属性具备响应式------------------------------------------------------
 */
const refLabel = ref({
  content: 12,
  name: 'xx'
})
const reactiveLabel = reactive({
  num: 19,
  name: 'xx'
})
let { content } = toRefs(refLabel.value)
let { num } = reactiveLabel
const changeContent = throttle(() => {
  content.value++
  console.log(content.value, '>>>>>>>>')
  // num++
}, 1000)
const changeNum = () => {
  // content.value++
  num--
}
/**
 * @description 测试调用本地JSON数据------------------------------------------------------------------------------------------------------------
 */
const localJson = ref()
const getTestData = params => {
  Axios({
    // url需要写绝对路径
    url: '/v1/test/testData',
    method: 'get',
    params
  }).then(res => {
    console.log(res)
    const { data } = res.data
    localJson.value = data
  })
}
/**
 * 浏览器控制台监听------------------------------------------------------------------------------------------------------------------------------------------------------------------
 */
import * as devtoolsDetector from 'devtools-detector'
// const view = document.createElement('div')
// document.body.appendChild(view)

// 1. add listener
devtoolsDetector.addListener(isOpen => {
  console.log('isOpen', isOpen)
})
// 2. launch detect
// devtoolsDetector.launch()

/**
 * @description 鼠标移动显示下拉列表，不同目标位置下拉列表内容不同------------------------------------------------------------------------------------------------------------------------------------------------------------------
 */
const { foods } = state

/**
 * @description flex布局（收起、展开）------------------------------------------------------------------------------------------------------------------------------------------------------------------
 */
const show = ref(true)
const changeShow = () => {
  show.value = !show.value
}

/**
 * @description 测试滚动条滚动监听调用接口数据------------------------------------------------------------------------------------------------------------------------------------------------------------------
 */
const scrollData_1 = ref([])
const scroll_content_1 = ref()
const scroll_son_1 = ref()
let length = 0
// 模拟接口数据调用
const scrollApi = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      length++
      const amountToAdd = 10
      const newObjects = Array.from({ length: amountToAdd }, () => ({
        context: '从API获取的新数据' + length
      }))
      // 如果你的API能返回实际数据，这里应替换成实际的获取过程
      // 如：newObjects = await axios.get('your-api-url').then(res => res.data.slice(0, amountToAdd));

      scrollData_1.value = scrollData_1.value.concat(newObjects)
      resolve('请求成功')
    }, 500)
  })
}

const handleScroll = val => {
  console.log(val, 'handleScroll___________val')
  const { scrollTop, scrollLeft, scrollWidth, scrollHeight, clientHeight } = val.target
  if (scrollTop + clientHeight >= scrollHeight - 10) {
    scrollApi()
  }
  console.log(scrollTop, scrollHeight, clientHeight)
}
const debounceHandleScroll = throttle(handleScroll, 500)
/**
 * @returns 查看目标元素的scroll各项属性值
 */
const divRef = async div => {
  await nextTick()
  if (div) {
    // 创建一个对象存储所有需要的属性
    const elementInfo = {
      attributes: {},
      scroll: {
        // 变量scrollTop是滚动条滚动时，距离顶部的距离
        scrollTop: div.scrollTop,
        // 变量scrollLeft是滚动条滚动时，距离左侧的距离
        scrollLeft: div.scrollLeft,
        // 变量scrollWidth是滚动条滚动时，滚动条的宽度
        scrollWidth: div.scrollWidth,
        // scrollHeight就是一个元素能够展示其“所有内容”所需要的最小高度，是元素整个的content加上padding的高度，不包括border。
        scrollHeight: div.scrollHeight,
        // “可视高度”，元素的content + padding的高度，不包括border、margin也不包括横向滚动条的高度。clientHeight的高度包括了这个元素伪元素(::before、::after)的高度。
        // 如果该元素的内容没有产生纵向滚动条的话，该元素的scrollHeight和clientHeight相等。
        clientHeight: div.clientHeight
      }
    }
    // 遍历并添加标准属性到对象
    Array.from(div.attributes).forEach(attribute => {
      elementInfo.attributes[attribute.name] = attribute.value
    })

    console.log('Element Info:', elementInfo)
  }
}
// 《--------------------------------------------------------滚动懒加载，命令行（main.js）封装使用--------------------------------------------------------------------------------------------------------------------------------------------》

const scrollBinding = throttle(scrollApi, 5000)

// 《--------------------------------------------------------滚动条自动滚动，鼠标移入停止滚动---------------------------------------------------------------------------------------------------------------------------------------------》
import { scrollAuto } from '@/utils/utils'
const scrollData_2 = ref([])
const scroll_content_2 = ref()
let autoScroll_timer = null
const autoScroll = () => {
  const { scrollTop, scrollLeft, scrollWidth, scrollHeight, clientHeight } = scroll_content_2.value

  // 判断是否有滚动条
  if (scrollHeight <= clientHeight) return
  // 当有滚动条时，判断是否滚到到底部
  if (scrollTop + clientHeight >= scrollHeight) {
    scroll_content_2.value.scrollTop = 0
  } else {
    scroll_content_2.value.scrollTop += 1
  }
}
//鼠标移入清除定时器
const autoScroll_Fn = () => {
  if (autoScroll_timer) {
    clearInterval(autoScroll_timer)
    autoScroll_timer = null
  } else {
    autoScroll_timer = setInterval(autoScroll, 50)
  }
}
// 《--------------------------------------------------------滚动条自动滚动(方法封装)，鼠标移入停止滚动---------------------------------------------------------------------------------------------------------------------------------------------》
//  v-scroll.mouse="0.5"
// 《--------------------------------------------------------滚动条自动滚动(方法封装)，鼠标移入停止滚动---------------------------------------------------------------------------------------------------------------------------------------------》

onMounted(() => {
  scrollApi()
  scrollApi().then(() => {
    scrollData_2.value = scrollData_1.value
  })
  divRef(scroll_content_1.value)
  divRef(scroll_son_1.value)
  scroll_content_1.value.addEventListener('scroll', debounceHandleScroll)
  // scrollAuto(scroll_content_2.value, 50)
  autoScroll_Fn()
  scroll_content_2.value.addEventListener('mouseenter', autoScroll_Fn)
  scroll_content_2.value.addEventListener('mouseleave', autoScroll_Fn)
})
onBeforeUnmount(() => {
  scroll_content_1.value.removeEventListener('scroll', debounceHandleScroll)
  clearInterval(autoScroll_timer)
  scroll_content_2.value.removeEventListener('mouseenter', autoScroll_Fn)
  scroll_content_2.value.removeEventListener('mouseleave', autoScroll_Fn)
})
</script>
<style lang="scss" scoped>
.Box {
  width: 100%;
  display: flex;
  justify-content: center;
  flex-direction: column;
  align-items: center;
}
.testBox {
  margin-bottom: 20px;
  &::after {
    content: '';
    display: block;
    width: 100%;
    height: 1px;
    background-color: #575454;
    position: relative;
    left: 50%;
    transform: translateX(-50%);
    margin-top: 20px;
  }
}
.flex-box {
  display: flex;
}
.father {
  width: 400px;
}
.testPop {
  height: 150px;
  display: flex;
  .content-box {
    position: relative;
    &:hover .pop-box {
      display: block;
    }
  }
  .item {
    width: 100px;
    height: 30px;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: cadetblue;
    color: aliceblue;
    border-radius: 3px;
    margin-left: 10px;
    // 重要！！！将父盒子的高度扩大到弹窗盒子的范围，这样鼠标移动到弹窗也不会消失
    margin-bottom: 10px;
    cursor: pointer;
  }
  .pop-box {
    display: none;
    margin-left: 10px;
    width: 130px;
    position: absolute;
    top: 40px;
    background-color: rgb(230, 133, 77);
    z-index: 10;
    .child {
      padding-left: 8px;
      height: 30px;
      display: flex;
      align-items: center;
      border-bottom: 1px solid rgb(229, 233, 238);
      &:hover {
        color: white;
        background-color: rgb(109, 115, 122);
      }
    }
  }
}
.testFlex {
  position: relative;
  display: flex;
  align-items: center;
  background-color: rgba(12, 12, 12, 0.733);
  height: 400px;
  width: 100%;
  .bottom {
    position: absolute;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    width: 20px;
    background-color: blue;
    color: white;
    cursor: pointer;
  }
  .leftBox {
    width: 150px;
    height: 300px;
    background-color: rgb(27, 150, 27);
    margin-right: 10px;
  }
  .midBox {
    flex: 1;
    width: 300px;
    height: 300px;
    margin-right: 10px;
    background-color: beige;
  }
  .rightBox {
    width: 200px;
    height: 300px;
    margin-right: 10px;
    background-color: rgb(167, 73, 39);
  }
}
.scroll-box {
  width: 400px;
  height: 300px;
  background-color: rgb(81, 190, 223);
  margin-right: 40px;
  margin-left: 40px;
  margin-bottom: 50px;

  .title {
    height: 40px;
    display: flex;
    justify-content: center;
    align-items: center;
  }
  .content {
    width: 100;
    height: 250px;
    background-color: rgb(221, 221, 67);
    overflow-y: scroll;

    .item {
      height: 30px;
      padding-left: 60px;
      border-bottom: 1px solid rgb(149, 187, 233);
    }
  }
}
</style>
